package org.custom.spring.boot.transaction.async;

import org.custom.spring.boot.transaction.entity.Transaction;
import org.custom.spring.boot.transaction.mapper.TransactionMapper;
import org.custom.spring.boot.transaction.service.transactional.AssistService;
import org.custom.spring.boot.transaction.utils.ValidUtil;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.util.concurrent.Future;

/**
 * 异步调用服务接口
 *
 * @author LiKun
 * @date 2021/9/17 8:39
 */
@Service
public class AsyncCall {
    @Resource
    private AssistService assistService;
    @Resource
    private TransactionMapper transactionMapper;

    @Async
    @Transactional
    public Future<Integer> transaction(String data) {
        return new AsyncResult<>(transactionMapper.insert(Transaction.getInstance(data)));
    }

    @Async
    @Transactional
    public Future<Integer> transactionException(String data) {
        transactionMapper.insert(Transaction.getInstance(data));
        return new AsyncResult<>(0);
    }

    @Async
    public Future<Integer> asyncWithoutTransactional(String data) {
        int insert = transactionMapper.insert(Transaction.getInstance(data));
        return new AsyncResult<>(ValidUtil.byZero());
    }

    @Async
    @Transactional
    public Future<Integer> asyncWithTransactionalAndException(String data) {
        int insert = transactionMapper.insert(Transaction.getInstance(data));
        return new AsyncResult<>(ValidUtil.byZero());
    }

    @Async
    public Future<Integer> asyncWithoutTransactionalAndException(String data) {
        int insert = transactionMapper.insert(Transaction.getInstance(data));
        return new AsyncResult<>(ValidUtil.byZero());
    }

    @Async
    @Transactional
    public Future<Integer> asyncOthersTransaction(String data1, String data2) {
        assistService.withoutTransaction(data1);
        return new AsyncResult<>(assistService.withTransaction(data2));
    }

    @Async
    @Transactional
    public Future<Integer> exception_and_manual_rollback_transaction(String data) {
        AsyncResult<Integer> asyncResult;
        try {
            transactionMapper.insert(Transaction.getInstance(data));
            asyncResult = new AsyncResult<>(ValidUtil.byZero());
        } catch (Exception exception) {
            asyncResult = new AsyncResult<>(1);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
        return asyncResult;
    }
}
